package com.lion.common.spring.enhancers.advices;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * 智能消息转换器，支持直接输出基础类型和自定义类型
 */
public class SmartMessageConverter extends AbstractHttpMessageConverter<Object> {
    private final ThreadLocal<Boolean> isWriting = ThreadLocal.withInitial(() -> false);
    // 定义直接输出（不转JSON）的基础类型列表
    private static final List<Class<?>> DIRECT_WRITE_TYPES = Arrays.asList(
            String.class, byte[].class,
            Byte.class, Short.class, Integer.class, Long.class,
            Float.class, Double.class, Boolean.class, Character.class,
            Void.class
    );

    // Jackson JSON处理器
    private final ObjectMapper objectMapper;

    // 构造器：支持JSON和纯文本两种媒体类型
    public SmartMessageConverter() {
        super(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN);
        // 初始化Jackson对象
        this.objectMapper = Jackson2ObjectMapperBuilder.json().build();
    }

    // 支持所有类型转换
    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }

    // 反序列化方法（本转换器仅用于响应输出，所以抛出异常）
    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) {
        // 如果是响应阶段（通过writeInternal设置的标记）
        if (isWriting.get()) {
            return null; // 交给其他转换器
        }
        throw new UnsupportedOperationException("This converter only supports response writing");
    }

    // 核心写入方法
    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException {
        try {
            isWriting.set(true);
            // 1. 检查是否为RestController的请求（避免影响文档接口等）
            if (!isRestControllerRequest()) {
                // 非控制器请求直接走JSON序列化
                objectMapper.writeValue(outputMessage.getBody(), object);
                return;
            }

            // 2. 判断是否应该直接输出原始值（不转JSON）
            if (shouldWriteDirectly(object)) {
                // 直接输出基本类型值
                writeDirectValue(object, outputMessage);
            } else {
                // 复杂对象走JSON序列化
                objectMapper.writeValue(outputMessage.getBody(), object);
            }
        } finally {
            isWriting.remove();
        }
    }

    // 判断当前请求是否来自@RestController
    private boolean isRestControllerRequest() {
        // 从请求上下文获取当前请求属性
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes instanceof ServletRequestAttributes) {
            // 获取原生HttpServletRequest
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            // 检查是否存在控制器映射（存在则表示是RestController请求）
            return request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingHandler") != null;
        }
        return false;
    }

    // 判断对象是否属于应该直接输出的类型
    private boolean shouldWriteDirectly(Object value) {
        if (value == null) return false;

        // 检查是否是定义的基础类型之一
        return DIRECT_WRITE_TYPES.stream()
                .anyMatch(type -> type.isInstance(value));
    }

    // 直接输出原始值的处理方法
    private void writeDirectValue(Object value, HttpOutputMessage outputMessage) throws IOException {
        String content;
        // 处理byte[]类型数据
        if (value instanceof byte[]) {
            content = new String((byte[]) value, StandardCharsets.UTF_8);
        } else {
            // 其他类型调用toString()
            content = value.toString();
        }

        // 设置响应头为text/plain
        outputMessage.getHeaders().setContentType(MediaType.TEXT_PLAIN);
        // 将内容写入响应体
        outputMessage.getBody().write(content.getBytes(StandardCharsets.UTF_8));
    }

    // 关键修改：重写canRead方法
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        // 永远不处理任何请求反序列化
        return false;
    }

    // 明确支持输出的类型
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        // 只处理这些类型的响应输出
        return String.class.isAssignableFrom(clazz) ||
                clazz.isPrimitive() ||
                Number.class.isAssignableFrom(clazz) ||
                Boolean.class == clazz || null == mediaType ||
                mediaType.includes(MediaType.TEXT_PLAIN);
    }
}